# -*- coding: utf-8 -*-
# created on 2016/12/19

import random
from sympy import sympify, Intersection, S
from sympy.core.function import UndefinedFunction
from mathsolver.functions.base import BaseFunction, BaseEq, BaseFuncName, BasePoly, BaseFuncEq, BaseValue, new_latex
from mathsolver.functions.hanshu.dingyiyu import QiuDingYiYu
from mathsolver.functions.hanshu.helper import yizhizhiyu_qiufanwei
from mathsolver.functions.hanshu.zhiyu import HanShuZhiYu
from mathsolver.functions.sympy_utils import get_all_child
from mathsolver.functions.hanshu.helper import check_inter


class AbstractHanShuDingYiYu(BaseFunction):
    """求抽象函数的定义域，已知 f(g(x)) 的定义域，求 f(h(x)) 或者 f(x)*h(x) 的定义域"""

    def solver(self, *args):

        gx, question_arg, dd = args[0].var, args[1], check_inter(args[2])

        # 求 y = f(x) 的定义域 D1
        dd1 = HanShuZhiYu().solver(BaseEq(['y', gx]), dd).output[0].value
        self.steps.append(["", "由题意知 y = f(x) 的定义域为 %s" % new_latex(dd1)])

        # 处理不同类型的输入
        if isinstance(question_arg, BaseFuncName):
            hx = question_arg.var
            # 由 f(x) 的定义域求 f(h(x)) 的定义域, h(x) ∈ D1
            res = yizhizhiyu_qiufanwei(hx, dd1)
            self.steps.append(["所以 %s ∈ %s" % (new_latex(hx), new_latex(dd1)), "所以定义域为 %s " % new_latex(res)])
        else:
            if isinstance(question_arg, BaseFuncEq):
                expr = sympify(question_arg.value[1])
            elif isinstance(question_arg, BasePoly):
                expr = sympify(question_arg.value)
            else:
                raise ValueError('unknown input type %s' % type(question_arg))

            # 求 expr 的定义域
            # f(h(x)) 部分函数
            fhxs = get_all_child(expr, lambda x: isinstance(x.func, UndefinedFunction))
            hxs = [fhx.args[0] for fhx in fhxs]
            self.steps.append(["", ' '.join(['%s ∈ %s' % (new_latex(hx), new_latex(dd1)) for hx in hxs])])

            # 非 f(h(x)) 部分函数, 用随机数替换 f(h(x))
            expr2 = expr.subs({fhx: random.randrange(10 ** i, 10 ** (i + 1)) for i, fhx in enumerate(fhxs)})
            dd3 = QiuDingYiYu().solver(BaseEq(['y', expr2]))
            if not dd3 == S.Reals:
                self.steps.append(["", "复合函数的定义域为 %s" % new_latex(dd3)])
            res = Intersection(dd3, dd3)
            self.steps.append(["", "所以 %s 的定义域为 %s " % (new_latex(expr), new_latex(res))])
        self.label.add("求抽象函数的定义域")
        self.output.append(BaseValue(res))
        return self


if __name__ == '__main__':
    pass
